package com.hanvon.paycheck.view;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import com.hanvon.core.HWColorPaint;
import com.hanvon.core.StrokeCollection;
import com.hanvon.paycheck.PaySignatureCheck;
import com.hanvon.signver.*;
//import com.pixcir.library.JniI2c;

import android.R.bool;
import android.R.integer;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.text.format.Time;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

public class StrokeView extends View{
    
    
	//画笔迹的Bitmap
    private Bitmap  mBitmap;
    private int[] mPixels;
    //背景像素数组
    private int[] mBackgroundPixels;   
    
    //画笔迹的Bitmap的高度与宽度
    private int mHeight;
    private int mWidth;    

    //包含所有笔迹的集合
    StrokeCollection mStrokes;
    
    //笔迹的三个属性：笔形，颜色，宽度
    int mPenStyle;
	int mColorType;
	int mPenWidth;
	
	//笔迹是否需要取压感值，如果没有就取1
	boolean mHasPressure = true;
	//控制是擦除还是画笔迹
	boolean mIsStroke = true;
	
	boolean mIsMove = false;

	Paint mPaint = new Paint();
	Canvas mCanvas;
	Rect refreshRect;
    
	Context cContext;
	public PaySignatureCheck mainActivty=null;
	public Boolean isCheck=false;
	
    public StrokeView(Context c, int width, int height) {
        super(c);
        cContext=c;  
		//int width = 1024, height = 600;
        mWidth = width;
        mHeight = height;
        
        if(mBitmap == null)
        {
        	try {
        		mBitmap = Bitmap.createBitmap( width, height, Bitmap.Config.RGB_565 );
            	mPixels = new int[width * height];            	
            }catch ( Exception e ) {
                //e.printStackTrace( );
                Toast toast = Toast.makeText(c,"error", Toast.LENGTH_LONG);
        		toast.setGravity(Gravity.CENTER, 0, 0);
        		toast.show();
            }
        	mBackgroundPixels = new int[width * height];
        }
        
        mCanvas = new Canvas(mBitmap);
        
        //初始化背景
        mBitmap.eraseColor(Color.WHITE);
        drawBackgroud(mBitmap, Color.GRAY);      
        //this.setBackgroundColor(Color.WHITE);
        
        mBitmap.getPixels( mPixels, 0, width, 0, 0, width, height );
        
        //save background        
        mBitmap.getPixels( mBackgroundPixels, 0, width, 0, 0, width, height );
        
        mStrokes = new StrokeCollection(width, height, mPixels, mBackgroundPixels);
  

        /* TEST */
        mPenStyle = 2; //閽㈢瑪
    	mColorType = 7;
    	mPenWidth = 5;

    	mPaint.setAntiAlias(true);
    	//mPaint.setDither(true);
    	//mPaint.setFlags (Paint.ANTI_ALIAS_FLAG);			
    	mPaint.setStrokeJoin(Paint.Join.ROUND);
    	mPaint.setStrokeCap(Paint.Cap.ROUND);
    	mPaint.setStyle(Paint.Style.STROKE);			
    	mPaint.setStrokeWidth(10.0f);  	 
    	

    }
    
    public void Destroy()
    {
    	if(mBitmap!=null)
    		mBitmap.recycle();
    	
    	mBitmap = null;
    }
  
    @Override
    protected void onDraw(Canvas canvas) { 
    	    	
    	if(mBitmap != null)
    		canvas.drawBitmap(mBitmap, 0, 0, null);
    }

    final Handler handler = new Handler(){  
    	      public void handleMessage(Message msg) {  
    	          switch (msg.what) {      
    	              case 1:    
    	            	  if (mStrokes!=null) {
    	            		  StrockOK();
    	            		  clear();

    	            		  
						  }    	            	 
    						if (null!=ttimerTimer) {
    			            	  ttimerTimer.cancel();
    			            	  ttimerTimer=null;
    						}
    	                  break;      
    	              }      
    	              super.handleMessage(msg);  
    	         }    
    	     };
    	    
   public byte[] template;
   public int numOfTempalte=0;
   public void StrockOK() {
		int sizeT=xList.size();
		  short[] xT=new short[sizeT];
		  short[] yT=new short[sizeT];
		  short[] tT=new short[sizeT];
		  short[] pT=new short[sizeT];
		  for (int i=0;i<xList.size();i++) {
			  xT[i]=xList.get(i);
			  yT[i]=yList.get(i);
			  tT[i]=timeTickList.get(i);
			  pT[i]=pressureList.get(i);
		}
		//--测试使用，获取笔迹，帮助算法部门调试识别核心--
//		  File sdCardDir = Environment.getExternalStorageDirectory();
//		  File saveFile = new File(sdCardDir,"Track");
//		
//		try {
//			byte [] tempSave={0,0};
//			FileOutputStream fOutputStream= new FileOutputStream(saveFile, true);
//			for (int i=0;i<xList.size();i++) {
//				tempSave[0] = (byte) (xT[i] >> 0);
//				tempSave[1]=(byte) (xT[i]  >> 8); 
//					fOutputStream.write(tempSave);
//					
//					tempSave[0] = (byte) (yT[i] >> 0);
//					tempSave[1]=(byte) (yT[i]  >> 8); 
//					fOutputStream.write(tempSave);
//					
//					tempSave[0] = (byte) (tT[i] >> 0);
//					tempSave[1]=(byte) (tT[i]  >> 8); 
//					fOutputStream.write(tempSave);
//					
//					tempSave[0] = (byte) (pT[i] >> 0);
//					tempSave[1]=(byte) (pT[i]  >> 8); 
//					fOutputStream.write(tempSave);
//					
//			}
//			tempSave[0] = (byte) (-100 >> 0);
//			tempSave[1]=(byte) (-100 >> 8);
//				fOutputStream.write(tempSave);
//				fOutputStream.write(tempSave);
//				fOutputStream.write(tempSave);
//				fOutputStream.write(tempSave);
//				fOutputStream.close(); 
//		} catch (FileNotFoundException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		catch (IOException e)
//		{
//			e.printStackTrace();
//		}
//		finally
//		{
//			
//		}
		//--测试使用，获取笔迹，帮助算法部门调试识别核心--
		//签名识别模式		
		  if (isCheck) {
			if (template!=null&&numOfTempalte==5) {

				  //识别签名
				  boolean nResult=SignVer.nativeSVCheckSig(template, sizeT, xT,yT,tT,pT);
				  if (nResult) {
					  //识别成功则更新签名模版
					
					if( SignVer.nativeSVGetUpdate()==1);
					{int ts=SignVer.nativeSVGetTemplLen();
					template=new byte[ts];
					SignVer.nativeSVGetTemplate(template);}
					Toast.makeText(cContext, "签名通过", Toast.LENGTH_SHORT).show();
					
				  }
				  else {
					  Toast.makeText(cContext, "签名未通过", Toast.LENGTH_SHORT).show();
				  }
			}
		}
		else {
		  //签名学习

		  //如果 模版数为5自动转换为识别模式
			if (numOfTempalte==5) {
			  
			  //签名识别
			  boolean nResult=SignVer.nativeSVCheckSig(template, sizeT, xT,yT,tT,pT);
			  if (nResult) {
				//签名识别
				  if( SignVer.nativeSVGetUpdate()==1); {
					int ts=SignVer.nativeSVGetTemplLen();
					if (ts>0) {
					template=null;
					System.gc();
					template=new byte[ts];
					SignVer.nativeSVGetTemplate(template);}
					Toast.makeText(cContext, "签名通过", Toast.LENGTH_SHORT).show();
//					//--记录模版--
//					try {
//						File saveTemplateFile = new File(sdCardDir,"template");
//						if (saveTemplateFile.exists()) {
//							  saveTemplateFile.delete();
//						}
//						FileOutputStream fOutputStream= new FileOutputStream(saveTemplateFile, true);
//						fOutputStream.write(template);
//						fOutputStream.close();
//					} catch (FileNotFoundException e) {
//						// TODO Auto-generated catch block
//						e.printStackTrace();
//					}
//					catch (IOException e)
//					{}
//				//--记录模版--
				}
			  }
			  else {
				  Toast.makeText(cContext, "签名未通过", Toast.LENGTH_SHORT).show();
			  }
		  }
		  else {
			  //学习签名
			  if (SignVer.nativeSVLearn(sizeT, xT,yT,tT,pT)) {
				  numOfTempalte++;
				  Toast.makeText(cContext, "第"+numOfTempalte+"次录制成功", Toast.LENGTH_SHORT).show();
				  if (numOfTempalte==5) {
					  //5次录制后，获取签名匹配模版
					  Toast.makeText(cContext, "录制完成", Toast.LENGTH_SHORT).show();
					  int ts=SignVer.nativeSVGetTemplLen();
					  if (ts>0) {
						  template=null;
						  System.gc();
						  template=new byte[ts];
						  SignVer.nativeSVGetTemplate(template);
//						  //--记录模版--
//						  File saveTemplateFile = new File(sdCardDir,"template");
//						  try {
//							if (saveTemplateFile.exists()) {
//								  saveTemplateFile.delete();
//							}
//							FileOutputStream fOutputStream= new FileOutputStream(saveTemplateFile, true);
//							fOutputStream.write(template);
//							fOutputStream.close();
//						} catch (FileNotFoundException e) {
//							// TODO Auto-generated catch block
//							e.printStackTrace();
//						}
//						  catch (IOException e)
//						  {}
//						//--记录模版--
					  }
					  else {
						  Toast.makeText(cContext, "模版录制失败", Toast.LENGTH_SHORT).show();
					}
					
				}
			}
			  else {
				  Toast.makeText(cContext, "签名过于简单", Toast.LENGTH_SHORT).show();
			}
			  
			  //SignVer.nativeSVLearn(sizeT, xT,yT,tT,pT);
			  
		  }
		  xList.clear();
		  yList.clear();
		  pressureList.clear();
		  timeTickList.clear();  
		}
} 	     
   
     private void setTimerTask() { 
    	 ttimerTimer.schedule(new TimerTask() {
			
			@Override
			public void run() {

			      Message message = new Message();      
			      message.what = 1;      
			      handler.sendMessage(message);  
			}
		}, 500);
     }

    
    ArrayList<Short> timeTickList=new ArrayList<Short>();
    ArrayList<Short> xList=new ArrayList<Short>();
    ArrayList<Short> yList=new ArrayList<Short>();
    ArrayList<Short> pressureList=new ArrayList<Short>();

    long ttick=0L;
    
    Timer ttimerTimer=new Timer(true);
	@SuppressLint({ "NewApi", "ParserError" })
	@TargetApi(14)
	@Override
    public boolean onTouchEvent(MotionEvent event) {

        int x = (int) event.getX();
        int y = (int) event.getY();   
       
        //getMetaState()的值针对A118
        if (event.getMetaState() != StrokeCollection.ERASER && mIsStroke) {
			float pressure = 0.8f;

			if(event.getMetaState() == StrokeCollection.PEN)
				pressure = event.getPressure();
			//Android4.0调用，判断第一个触控点类型，然后获取相应压感即可
			if(event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS)
			{
				pressure = event.getPressure();
			}
			if (event.getToolType(0) == MotionEvent.TOOL_TYPE_ERASER)
			{
				pressure = event.getPressure();
			}

			// 画笔迹	
			switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN:
				if (!mIsMove) {
					//调用方式二：mStrokes.addStroke(mPenStyle, Color.argb(255, 0, 0, 0), mPenWidth, true);
					mStrokes.addStroke(mPenStyle, mColorType, mPenWidth, false);
					mIsMove = true;	
					
					xList.add((short) 0);
					yList.add((short) 0);
					pressureList.add((short) 0);
					
					if (timeTickList.isEmpty()) {
						timeTickList.add((short) 0);
						ttick=SystemClock.elapsedRealtime();
					}
					else {
						
						timeTickList.add((short) (SystemClock.elapsedRealtime()-ttick));
					}
					
					//清除时间戳
					if (null!=ttimerTimer) {
		            	  ttimerTimer.cancel();
		            	  ttimerTimer=null;
					}

				}
				break;
			case MotionEvent.ACTION_MOVE:	
				refreshRect = mStrokes.add(new Point(x, y), pressure);
				if (refreshRect.width() != 0 && refreshRect.height() != 0) {
					
					mBitmap.setPixels(mPixels, refreshRect.top * mWidth
							+ refreshRect.left, mWidth,
							refreshRect.left, refreshRect.top,
							refreshRect.width(), refreshRect.height());
					
					
					xList.add((short) x);
					yList.add((short) y);
					pressureList.add((short) (pressure*1024));
					timeTickList.add((short) (SystemClock.elapsedRealtime()-ttick));
					invalidate(refreshRect);
				}
				break;
			case MotionEvent.ACTION_UP:
				// 笔迹结束的时候，传（-100，-100）通知结束				
				refreshRect = mStrokes.add(new Point(-100, -100), -100f);
				if (refreshRect.width() != 0 && refreshRect.height() != 0) {

					mBitmap.setPixels(mPixels, refreshRect.top * mWidth
							+ refreshRect.left, mWidth,
							refreshRect.left, refreshRect.top,
							refreshRect.width(), refreshRect.height());
					
					invalidate(refreshRect);
					xList.add((short) -1);
					yList.add((short) 0);
					pressureList.add((short) 0);
					timeTickList.add((short) 0);
					//timeTickList.add((short) -1);
					if (null==ttimerTimer) {
						ttimerTimer=new Timer(true);
						setTimerTask();
					}
					
					
				}
				mIsMove = false;
				break;
			default:
				break;
			}
		} else {
			// 擦除
			switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN:
			case MotionEvent.ACTION_MOVE:
				refreshRect = mStrokes.erase(new Point(x, y));
				if (refreshRect.width() != 0 && refreshRect.height() != 0) {
					mBitmap.setPixels(mPixels, refreshRect.top * mWidth
							+ refreshRect.left, mWidth,
							refreshRect.left, refreshRect.top,
							refreshRect.width(), refreshRect.height());
					invalidate(refreshRect);
				}
				break;
			case MotionEvent.ACTION_UP:
				// 此次擦除完成，也需要传（-1，-1）通知结束
				refreshRect = mStrokes.erase(new Point(-1, -1));
				if (refreshRect.width() != 0 && refreshRect.height() != 0) {
					mBitmap.setPixels(mPixels, refreshRect.top * mWidth
							+ refreshRect.left, mWidth,
							refreshRect.left, refreshRect.top,
							refreshRect.width(), refreshRect.height());
					invalidate(refreshRect);
				}
				break;
			default:
				break;
			}
		}
        
        return true;
    }
    
    public void reDraw()
    {
    	Rect refreshRect = mStrokes.reDraw();
    	
    	if(refreshRect.width() != 0 && refreshRect.height()!=0)
    	{
    		mBitmap.setPixels( mPixels, refreshRect.top * mWidth + refreshRect.left, mWidth, 
        			refreshRect.left, refreshRect.top, refreshRect.width(), refreshRect.height());
        	invalidate(refreshRect);
    	}
    }
    
    public void setTestDistance()
    {
    }
    
	public void erase() {
		//切换擦除和画笔迹
		if(mIsStroke)
			mIsStroke = false;
		else
			mIsStroke = true;
	}

	public void updateColor() {
		++mColorType;
		if (mColorType > 14 && mColorType < 100) {
			mColorType = 100;
		} else if (mColorType > 112) {
			mColorType = 0;
		}
		mIsStroke = true;
	}

	public void updateWidth() {
		mPenWidth = (mPenWidth + 1) % 6;
		if(mPenWidth == 0)
			mPenWidth = 1;
		mIsStroke = true;
	}

	public void updateStyle() {
		mPenStyle = (mPenStyle + 1) % 5;
		if(mPenStyle == 0)
			mPenStyle = 1;
		mIsStroke = true;
	}
	
	public void updatePressure() {
		if(mHasPressure)
			mHasPressure = false;
		else
			mHasPressure=true;
		mIsStroke = true;
	}
	
	public void clear() 
	{
		//清空所有笔迹
		mStrokes.clearBackground();
		
		Rect refreshRect = new Rect(0, 0, mWidth, mHeight);
		if(refreshRect.width() != 0 && refreshRect.height()!=0)
    	{
    		mBitmap.setPixels( mPixels, refreshRect.top * mWidth + refreshRect.left, mWidth, 
        			refreshRect.left, refreshRect.top, refreshRect.width(), refreshRect.height());
        	invalidate(refreshRect);
    	}
	}
	
	boolean isChange = true;
	public void updateBackground() 
	{
		 mBitmap.eraseColor(Color.WHITE);

		 if(isChange)
		 {
			 drawBackgroud(mBitmap, Color.BLUE);
			 isChange = false;
		 }
		 else
		 {
			 drawBackgroud(mBitmap, Color.GRAY);
			 isChange = true;
		 }
         
         mBitmap.getPixels( mPixels, 0, mWidth, 0, 0, mWidth, mHeight );
         mBitmap.getPixels( mBackgroundPixels, 0, mWidth, 0, 0, mWidth, mHeight );
         
         
         Rect refreshRect = new Rect(0, 0, mWidth, mHeight);
 		if(refreshRect.width() != 0 && refreshRect.height()!=0)
     	{
     		mBitmap.setPixels( mPixels, refreshRect.top * mWidth + refreshRect.left, mWidth, 
         			refreshRect.left, refreshRect.top, refreshRect.width(), refreshRect.height());
         	invalidate(refreshRect);
     	}
	}
	
	private void drawBackgroud(Bitmap bitmap, int color)
	{
		Canvas canvas = new Canvas(bitmap);
		
		int width = canvas.getWidth();
    	int height = canvas.getHeight();
    	
    	Path path = new Path(); 
    	
    	float cmUnit = 4 * 10;
    	
    	int distance = (int)(width/cmUnit) + 1;
    	for(int i = 1; i < distance; i++)
    	{
    		path.moveTo((int)(i*cmUnit), 0);
    		path.lineTo((int)(i*cmUnit), height);
    	}
    	
    	distance= (int)(height/cmUnit) + 1;
    	for(int i = 1; i < distance; i++)
    	{
    		path.moveTo(0, (int)(i*cmUnit));
    		path.lineTo(width, (int)(i*cmUnit));
    	}
    	
    	Paint paint = new Paint();
    	paint.setAntiAlias(true);
    	paint.setColor(color);
    	paint.setAlpha(255);
    	paint.setStyle(Paint.Style.STROKE);
    	
    	DashPathEffect mEffects =  new DashPathEffect(new float[] {5, 5, 5, 5}, 1); 
    	paint.setPathEffect(mEffects);
    	paint.setStrokeWidth(1.0f);

		canvas.drawPath(path, paint);
	}
	
	
	private void int2bytes(int[] ints, byte[] bytes) {
		for (int i = 0; i < ints.length; i++) {
			bytes[4 * i] = (byte) (ints[i] >>> (24 - 0 * 8));
			bytes[4 * i + 1] = (byte) (ints[i] >>> (24 - 1 * 8));
			bytes[4 * i + 2] = (byte) (ints[i] >>> (24 - 2 * 8));
			bytes[4 * i + 3] = (byte) (ints[i] >>> (24 - 3 * 8));
		}
	}

	private void bytes2ints(int[] ints, byte[] bytes) {
		for (int i = 0; i < ints.length; i++) {
			ints[i] = 0;
			ints[i] <<= 8;
			ints[i] |= (bytes[4 * i] & 0x000000ff);
			ints[i] <<= 8;
			ints[i] |= (bytes[4 * i + 1] & 0x000000ff);
			ints[i] <<= 8;
			ints[i] |= (bytes[4 * i + 2] & 0x000000ff);
			ints[i] <<= 8;
			ints[i] |= (bytes[4 * i + 3] & 0x000000ff);
		}
	}

	public void saveMyBitmap(String bitName) throws IOException {
		File f = new File("/sdcard/movie/" + bitName + ".png");
		f.createNewFile();
		FileOutputStream fOut = null;
		try {
			fOut = new FileOutputStream(f);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
		try {
			fOut.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			fOut.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
